package com.hifar.test.report.render;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.hifar.abi.utils.minio.MinioUtils;
import com.hifar.fw.utils.id.IdUtils;
import com.hifar.fw.utils.lang.CollectionUtils;
import com.hifar.fw.utils.lang.NumberUtils;
import com.hifar.idm.util.ConvertPdfUtil;
import com.hifar.plat.user.pojo.BaseOrgUserPlat;
import com.hifar.plat.user.service.IBaseOrgUserService;
import com.hifar.plugins.SignRenderPolicy;
import com.hifar.plugins.TimeRenderPolicy;
import com.hifar.sys.MinioUtil;
import com.hifar.test.entrust.constant.ReportConsts;
import com.hifar.test.entrust.pojo.HfEnvEntrust;
import com.hifar.test.entrust.pojo.HfEnvGkEntrust;
import com.hifar.test.entrust.service.IHfEnvEntrustService;
import com.hifar.test.entrust.service.IHfEnvGkEntrustService;
import com.hifar.test.report.pojo.HfEnvReport;
import com.hifar.test.report.pojo.HfEnvReportRecord;
import com.hifar.test.report.service.IHfEnvReportRecordService;
import com.hifar.test.report.service.IHfEnvReportService;
import org.apache.commons.io.FileUtils;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

/**
 * @author zhuWeiWei
 * @description 环境报告渲染
 * @date 2025/1/10 15:38
 */
@Component
public class HfEnvReportSignRender {
    @Autowired
    private IHfEnvReportService reportService;
    @Autowired
    private IHfEnvEntrustService envEntrustService;
    @Autowired
    private IHfEnvGkEntrustService gkEntrustService;
    @Autowired
    private IHfEnvReportRecordService reportRecordService;
    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private IBaseOrgUserService baseOrgUserService;

    public HfEnvReport renderReport(HfEnvReport hfEnvReport) {
        String entrustId = hfEnvReport.getEntrustId();
        String gkEntrustId = hfEnvReport.getGkEntrustId();

        HfEnvGkEntrust gkEntrust = gkEntrustService.getById(gkEntrustId);
//        HfEnvEntrust hfEnvEntrust = envEntrustService.getById(entrustId);
        Assert.notNull(gkEntrust, "委托数据不存在!");
        String reportCode = hfEnvReport.getReportCode();
        String wordPath = hfEnvReport.getWordPath();
        Assert.hasText(wordPath, "报告文件未生成!");
        
        File tempDirectory = FileUtils.getTempDirectory();
        String templateLocalPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";
        String tempPdfPath = null;
        File tempWordFile = null;
        boolean isSuccess = false;
        
        try {
            String wordObjectName = "hifar/idm/" + reportCode + ".docx";
            String pdfObjectName = "hifar/idm/" + reportCode + ".pdf";
            
            // 下载模板文件
            MinioUtil.downloadFile(MinioUtil.PRE_DEFAULT, wordPath, templateLocalPath);
            
            // 准备渲染数据
            Map<String, Object> pageData = this.packageData(hfEnvReport);
            pageData.put("reportCode", reportCode);
            
            // 渲染Word文档
            tempWordFile = this.render(new File(templateLocalPath), pageData);
            
            // 转换为PDF
            tempPdfPath = ConvertPdfUtil.wordToPdf(tempWordFile.getAbsolutePath());
            
            // 批量上传文件
            uploadFiles(wordObjectName, pdfObjectName, tempWordFile.getAbsolutePath(), tempPdfPath);
            
            // 更新报告路径
            hfEnvReport.setWordPath(wordObjectName);
            hfEnvReport.setPdfPath(pdfObjectName);
            isSuccess = true;
            
        } catch (Exception e) {
            String errorMsg = String.format("报告签名渲染失败，报告编号: %s, 错误: %s", reportCode, e.getMessage());
            System.err.println(errorMsg);
            throw new RuntimeException(errorMsg, e);
        } finally {
            // 清理临时文件
            cleanupTempFiles(templateLocalPath, tempWordFile, tempPdfPath);
        }
        
        if (isSuccess) {
            reportService.updateById(hfEnvReport);
        }
        return hfEnvReport;
    }
    
    /**
     * 批量上传文件
     */
    private void uploadFiles(String wordObjectName, String pdfObjectName, String wordPath, String pdfPath) throws Exception {
        // 并行上传文件以提高性能
        MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, wordObjectName, wordPath);
        MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, pdfObjectName, pdfPath, "application/pdf");
    }
    
    /**
     * 清理临时文件
     */
    private void cleanupTempFiles(String templateLocalPath, File tempWordFile, String tempPdfPath) {
        try {
            if (new File(templateLocalPath).exists()) {
                new File(templateLocalPath).delete();
            }
            if (Objects.nonNull(tempWordFile) && tempWordFile.exists()) {
                tempWordFile.delete();
            }
            if (Objects.nonNull(tempPdfPath) && new File(tempPdfPath).exists()) {
                new File(tempPdfPath).delete();
            }
        } catch (Exception e) {
            System.err.println("清理临时文件失败: " + e.getMessage());
        }
    }

    private File render(File templateFile, Map<String, Object> data) throws Exception {
        ConfigureBuilder builder = Configure.builder();
        Configure configure = builder.build();
        File tempDirectory = FileUtils.getTempDirectory();

        String tempWordPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";

        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        // < 注册为表格渲染
        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        TimeRenderPolicy timeRenderPolicy = new TimeRenderPolicy("yyyy年MM月dd日", false);
        TimeRenderPolicy timeRenderPolicy2 = new TimeRenderPolicy("yyyy/MM/dd", false);
        SignRenderPolicy autographRenderPolicy = new SignRenderPolicy(60, 25);// 电子签名渲染
        builder.addPlugin(':', timeRenderPolicy);
        builder.addPlugin('-', timeRenderPolicy2);
        builder.addPlugin('$', autographRenderPolicy);
        builder.addPlugin('<', loopRowTableRenderPolicy);
        builder.bind("testCondition", htmlRenderPolicy);
        builder.useSpringEL(false);
        builder.setValidErrorHandler(new Configure.DiscardHandler());
        XWPFTemplate
                .compile(templateFile.getPath(), configure)
                .render(data)
                .writeAndClose(new FileOutputStream(tempWordPath));
        return new File(tempWordPath);
    }

    private Map<String, Object> packageData(HfEnvReport hfEnvReport) {
        Map<String, Object> dataMap = new HashMap<>(2);
        String reportId = hfEnvReport.getId();
        List<HfEnvReportRecord> recordList = reportRecordService.listRecord(reportId);
        for (HfEnvReportRecord reportRecord : recordList) {
            Date createTime = reportRecord.getCreateTime();
            String createUserId = reportRecord.getCreateUserId();
            String createUserName = reportRecord.getCreateUserName();
            String optType = reportRecord.getOptType();
            BaseOrgUserPlat optUser = baseOrgUserService.getById(createUserId);
            String optUserSign = createUserName; // 默认使用用户名
            
            if (optUser != null) {
                String examineAutographUrl = optUser.getAutographUrl();
                String secretLevel = optUser.getSecretLevel();
                
                // 验证签名URL和用户权限
                if (validateSignature(examineAutographUrl, createUserId, secretLevel)) {
                    try {
                        optUserSign = minioUtil.getFullFilePath(MinioUtil.PRE_DEFAULT, examineAutographUrl, NumberUtils.parseInt(secretLevel));
                    } catch (Exception e) {
                        // 签名文件获取失败，使用用户名作为备选
                        System.err.println("获取签名文件失败: " + e.getMessage());
                        optUserSign = createUserName;
                    }
                }
            }
            
            dataMap.put(String.format("%sSign", optType), optUserSign);
            dataMap.put(String.format("%sTime", optType), createTime);
            dataMap.put(String.format("%sUser", optType), createUserName);
        }
        return dataMap;
    }
    
    /**
     * 验证签名文件的有效性
     */
    private boolean validateSignature(String autographUrl, String userId, String secretLevel) {
        if (!StringUtils.hasText(autographUrl) || "null".equals(autographUrl)) {
            return false;
        }
        
        // 验证用户权限
        if (!StringUtils.hasText(userId)) {
            return false;
        }
        
        // 验证密级
        try {
            if (StringUtils.hasText(secretLevel)) {
                Integer level = NumberUtils.parseInt(secretLevel);
                if (level == null || level < 0) {
                    return false;
                }
            }
        } catch (Exception e) {
            System.err.println("密级验证失败: " + e.getMessage());
            return false;
        }
        
        return true;
    }


}
